package com.ruoyi.system.utils;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.ruoyi.system.config.OSSConfig;
import com.ruoyi.system.utils.po.OSSUrlImagePO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PreDestroy;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.UUID;

@Slf4j
@Component
public class OSSUtil {

    @Autowired
    private OSSConfig ossConfig;
    
    @Autowired
    private OSSClient ossClient; // 注入单例OSSClient

    /**
     * 上传图片并返回正常路径（永久路径）
     */
    public String uploadImageGetNormalUrl(MultipartFile file) {
        return uploadImageGetNormalUrl(file, null);
    }

    /**
     * 上传图片并返回正常路径（永久路径）
     */
    public String uploadImageGetNormalUrl(MultipartFile file, String folder) {
        String fileName = uploadToOSS(file, folder);
        return generateNormalUrl(fileName);
    }

    /**
     * 上传图片并返回加密路径（临时路径）
     */
    public String uploadImageGetEncryptedUrl(MultipartFile file) {
        OSSUrlImagePO ossUrlImagePO = uploadImageGetEncryptedUrl(file, null);
        return ossUrlImagePO.getUrl();
    }

    /**
     * 上传图片并返回加密路径（临时路径）
     */
    public OSSUrlImagePO uploadImageGetEncryptedUrl(MultipartFile file, String folder) {
        String fileName = uploadToOSS(file, folder);
        String encryptedUrl = generateEncryptedUrl(fileName);
        OSSUrlImagePO ossUrlImagePO = new OSSUrlImagePO().builder().url(encryptedUrl).fileName(fileName).build();
        return ossUrlImagePO;
    }

    /**
     * 上传文件到OSS（核心方法）
     */
    private String uploadToOSS(MultipartFile file, String folder) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("文件不能为空");
        }

        // 验证文件类型
        String originalFilename = file.getOriginalFilename();
        String fileExtension = getFileExtension(originalFilename);
        if (!isImageFile(fileExtension)) {
            throw new IllegalArgumentException("只支持图片文件上传");
        }

        try {
            // 生成文件名
            String fileName = generateFileName(originalFilename, folder);
            
            // 创建元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            metadata.setContentType(getContentType(fileExtension));
            
            // 上传文件
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    ossConfig.getBucketName(), 
                    fileName, 
                    file.getInputStream(), 
                    metadata
            );
            
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            log.info("图片上传成功，文件名: {}, ETag: {}", fileName, result.getETag());
            
            return fileName;
            
        } catch (IOException e) {
            log.error("文件读取失败", e);
            throw new RuntimeException("文件上传失败", e);
        }
    }

    /**
     * 生成正常URL（永久路径）
     */
    public String generateNormalUrl(String fileName) {
        if (ossConfig.getDomain() != null && !ossConfig.getDomain().isEmpty()) {
            // 使用自定义域名
            return ossConfig.getDomain() + "/" + fileName;
        } else {
            // 使用OSS默认域名
            return "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/" + fileName;
        }
    }

    /**
     * 生成加密URL（临时路径）
     */
    public String generateEncryptedUrl(String fileName) {
        URL url = generateEncryptedUrl(fileName, ossConfig.getExpireTime());
        return url.toString();
    }

    /**
     * 生成加密URL（临时路径）
     */
    public URL generateEncryptedUrlBean(String fileName) {
        return generateEncryptedUrl(fileName, ossConfig.getExpireTime());
    }

    /**
     * 生成加密URL（临时路径）
     */
    public URL generateEncryptedUrl(String fileName, int expireMinutes) {
        // 设置URL过期时间
        Date expiration = new Date(System.currentTimeMillis() + expireMinutes * 60 * 1000L);
        
        // 生成签名URL
        URL url = ossClient.generatePresignedUrl(ossConfig.getBucketName(), fileName, expiration);
//
//        String encryptedUrl = url.toString();
//
//        // 如果配置了自定义域名，则替换默认域名
//        if (ossConfig.getDomain() != null && !ossConfig.getDomain().isEmpty()) {
//            encryptedUrl = encryptedUrl.replace(
//                "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint(),
//                ossConfig.getDomain()
//            );
//        }
//
//        log.info("生成加密URL，文件名: {}, 过期时间: {}分钟", fileName, expireMinutes);
//        return encryptedUrl;
        return url;
    }

    /**
     * 根据现有文件获取正常URL
     */
    public String getNormalUrl(String fileName) {
        return generateNormalUrl(fileName);
    }

    /**
     * 根据现有文件获取加密URL
     */
    public String getEncryptedUrl(String fileName) {
        return generateEncryptedUrl(fileName);
    }

    /**
     * 根据现有文件获取加密URL
     */
    public String getEncryptedUrl(String fileName, int expireMinutes) {
        URL url = generateEncryptedUrl(fileName, expireMinutes);
        return url.toString();
    }

    public URL uploadImage(MultipartFile file, String folder) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("文件不能为空");
        }

        // 验证文件类型
        String originalFilename = file.getOriginalFilename();
        String fileExtension = getFileExtension(originalFilename);
        if (!isImageFile(fileExtension)) {
            throw new IllegalArgumentException("只支持图片文件上传");
        }


        try {

            // 生成文件名
            String fileName = generateFileName(originalFilename, folder);

            // 创建元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            metadata.setContentType(getContentType(fileExtension));

            // 上传文件
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    ossConfig.getBucketName(),
                    fileName,
                    file.getInputStream(),
                    metadata
            );

            PutObjectResult result = ossClient.putObject(putObjectRequest);
            log.info("图片上传成功，ETag: {}", result.getETag());

            // 生成加密URL
            return generateEncryptedUrlBean(fileName);

        } catch (Exception e) {
            log.error("文件读取失败", e);
            throw new RuntimeException("文件上传失败", e);
        }
//        finally {
//            if (ossClient != null) {
//                ossClient.shutdown();
//            }
//        }
    }

    /**
     * 上传字节数组图片
     */
    public String uploadImage(byte[] bytes, String originalFileName, String folder, boolean needEncrypt) {
        String fileName = uploadToOSS(bytes, originalFileName, folder);
        if (needEncrypt) {
            return generateEncryptedUrl(fileName);
        } else {
            return generateNormalUrl(fileName);
        }
    }

    /**
     * 上传字节数组到OSS
     */
    private String uploadToOSS(byte[] bytes, String originalFileName, String folder) {
        if (bytes == null || bytes.length == 0) {
            throw new IllegalArgumentException("文件内容不能为空");
        }

        String fileName = generateFileName(originalFileName, folder);
        
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(bytes.length);
        metadata.setContentType(getContentType(getFileExtension(originalFileName)));
        
        PutObjectRequest putObjectRequest = new PutObjectRequest(
                ossConfig.getBucketName(), 
                fileName, 
                new ByteArrayInputStream(bytes), 
                metadata
        );
        
        PutObjectResult result = ossClient.putObject(putObjectRequest);
        log.info("图片上传成功，文件名: {}, ETag: {}", fileName, result.getETag());
        
        return fileName;
    }

    /**
     * 删除OSS文件
     */
    public void deleteFile(String fileName) {
        ossClient.deleteObject(ossConfig.getBucketName(), fileName);
        log.info("文件删除成功: {}", fileName);
    }

    /**
     * 生成文件名（按日期分文件夹）
     */
    private String generateFileName(String originalFileName, String folder) {
        String fileExtension = getFileExtension(originalFileName);
        String uuid = UUID.randomUUID().toString().replace("-", "");
        String fileName = uuid + "." + fileExtension;
        
        // 生成日期文件夹
        String dateFolder = getCurrentDateFolder();
        
        if (folder != null && !folder.isEmpty()) {
            folder = folder.replaceAll("^/|/$", "");
            return folder + "/" + dateFolder + "/" + fileName;
        }
        
        return dateFolder + "/" + fileName;
    }

    /**
     * 获取当前日期文件夹
     */
    private String getCurrentDateFolder() {
        return java.time.LocalDate.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"));
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        if (fileName == null || fileName.lastIndexOf(".") == -1) {
            return "jpg";
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
    }

    /**
     * 检查是否为图片文件
     */
    private boolean isImageFile(String fileExtension) {
        String[] imageExtensions = {"jpg", "jpeg", "png", "gif", "bmp", "webp"};
        for (String ext : imageExtensions) {
            if (ext.equals(fileExtension)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取Content-Type
     */
    private String getContentType(String fileExtension) {
        switch (fileExtension) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "bmp":
                return "image/bmp";
            case "webp":
                return "image/webp";
            default:
                return "application/octet-stream";
        }
    }

    //截取第一个/后面的字符串
    public   String getFileNameSub(String fileName) {
        if (fileName == null || fileName.isEmpty()) {
            return "";
        }
        int index = fileName.indexOf("/");
        if (index == -1) {
            return fileName;
        }
        return fileName.substring(index + 1);
    }

    /**
     * 应用关闭时销毁OSSClient
     */
    @PreDestroy
    public void destroy() {
        if (ossClient != null) {
            ossClient.shutdown();
            log.info("OSSClient已关闭");
        }
    }
}